/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "设备内存缓存.h"

//#include "shader_ray.h"
//#include <stdarg.h>
//#include <几何数据.h>

//#include <缓存.h>


#include "底层绘图/intern/Vulkan/buffer/Vk缓存.h"

struct S_缓存调试分配记录 {
	std::string	fileName;
	uint32		编号;
};

static std::map<S_板载缓存*, uint32> 分配释放记录;
static std::mutex g缓存分配锁;

//S_Mesh* S_全局缓存::m_方形区域光物体网格 = nullptr;
//S_Mesh* S_全局缓存::m_圆形区域光物体网格 = nullptr;
//S_板载缓存* S_全局缓存::g_顶层加速结构构建缓存 = nullptr;
//S_板载缓存* S_全局缓存::m_场景物体网格属性 = nullptr;
//S_板载缓存* S_全局缓存::m_几何属性 = nullptr;
//S_板载缓存* S_全局缓存::m_2D线 = nullptr;
//S_板载缓存* S_全局缓存::m_2D面板变换 = nullptr;
//S_板载缓存* S_全局缓存::g_字符纹理UV = nullptr;
//S_板载缓存* S_全局缓存::g_字符 = nullptr;
//S_板载缓存* S_全局缓存::g_凸包图元 = nullptr;
//S_板载缓存* S_全局缓存::g_凸包图元区域 = nullptr;
//S_板载缓存* S_全局缓存::g_波形属性 = nullptr;
//S_板载缓存* S_全局缓存::g_材质 = S_全局缓存::g_材质 ? S_全局缓存::g_材质 : nullptr;
//S_GPU内存块 S_全局缓存::m_材质 = S_全局缓存::m_材质.m_Buf ? S_全局缓存::m_材质 : S_GPU内存块{};
//S_板载缓存* S_全局缓存::g_光追物体实例属性ID = nullptr;
//S_板载缓存* S_全局缓存::m_全局绑定参数指针 = nullptr;
//S_GPU内存块 S_全局缓存::g_全局绑定参数 = {};
//S_板载缓存* S_全局缓存::m_平行光缓冲区 = nullptr;
//S_板载缓存* S_全局缓存::m_点光源缓冲区 = nullptr;
//S_板载缓存* S_全局缓存::m_区域光缓冲区 = nullptr;
//S_板载缓存* S_全局缓存::m_聚光灯缓冲区 = nullptr;
//S_板载缓存* S_全局缓存::g_灯光属性ID = nullptr;
//S_板载缓存* S_全局缓存::m_I32动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_UI32动态属性 = nullptr;
//S_板载缓存* S_全局缓存::g_UI64缓存 = nullptr;
//S_板载缓存* S_全局缓存::m_F32动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_Vec2动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_Vec3动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_Vec4动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_iVec2动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_iVec3动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_iVec4动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_uVec2动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_uVec3动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_uVec4动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_Mat44动态属性 = nullptr;
//S_板载缓存* S_全局缓存::m_U_Mat44 = nullptr;
//S_板载缓存* S_全局缓存::g_采样曲线属性 = nullptr;
//S_板载缓存* S_全局缓存::g_纹理属性 = nullptr;
//S_板载缓存* S_全局缓存::g_实例材质ID = nullptr;
//S_板载缓存* S_全局缓存::g_MPM_坐标 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_前一帧坐标 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_速度和年龄 = nullptr;
//S_板载缓存* S_全局缓存::g_MPM_密度_lambda = nullptr;
//S_板载缓存* S_全局缓存::g_MPM_速度梯度 = nullptr;
//S_板载缓存* S_全局缓存::g_MPM_网格速度 = nullptr;
//S_板载缓存* S_全局缓存::g_MPM_网格密度 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_压力 = nullptr;
//S_板载缓存* S_全局缓存::m_Delta = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_粒子类型和状态 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_排序键值 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_排序临时键值 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_排序键值偏移A = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_排序键值偏移B = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_排序键值数量 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_粒子网格索引 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_PBF参数 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅坐标 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅速度 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅粒子寿命 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅排序键值 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅粒子发射排序键值 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_飞溅粒子发射区间数量 = nullptr;
//S_板载缓存* S_全局缓存::g_PHY_物理力 = nullptr;
//S_GPU内存块 S_全局缓存::g_灯光方向 = {};
//S_板载缓存* S_全局缓存::g_粒子位置 = nullptr;
//S_板载缓存* S_全局缓存::g_粒子速度 = nullptr;
//S_板载缓存* S_全局缓存::g_粒子旋转 = nullptr;
//S_板载缓存* S_全局缓存::g_粒子大小 = nullptr;
//S_GPU纹理参数槽 S_全局缓存::g_全局模型纹理槽 = {};
//S_板载缓存* S_全局缓存::g_自定义属性索引 = nullptr;

class C_缓存块列队拷贝 : public C_缓存列队数据 {
	const S_GPU内存块 m_数据源;
public:
	C_缓存块列队拷贝(S_GPU内存块* 拷贝目标, const S_GPU内存块& 拷贝源) : m_数据源(拷贝源) {
		m_拷贝目标 = 拷贝目标;
	}

	S_GPU偏移大小 f_分配空间() {
		f_bm_resize(*m_拷贝目标, m_数据源.m_Mem.m_数量);
		return m_拷贝目标->m_Mem;
	}

	void f_拷贝到GPU() {
		uint8* dst = &(((uint8*)(*m_拷贝目标).m_Buf->m_mappedPtr)[(*m_拷贝目标).m_Mem.m_偏移 * (*m_拷贝目标).m_Buf->m_Offset]);
		uint8* src = &(((uint8*)m_数据源.m_Buf->m_mappedPtr)[m_数据源.m_Mem.m_偏移 * m_数据源.m_Buf->m_Offset]);
		memcpy(dst, src, m_数据源.m_Mem.m_数量 * m_数据源.m_Buf->m_Offset);

		//f_bm_fill(*m_拷贝目标, (uint8*)m_数据源.data(), m_数据源.size());
	}
};





S_板载缓存* f_buf_create板载缓存(S_设备环境& ctx, uint16 offset, E_板载缓存类型 type, uint64 size) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, offset, type, size);
	assert(offset);
	g缓存分配锁.lock();
	
	分配释放记录[buf] = 分配释放记录.size();

	g缓存分配锁.unlock();
	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境& ctx, E_板载缓存类型 type, uint32 typeflags, uint16 offset, uint64 size) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, type, f_getVk缓存类型(typeflags), offset, size);
	
	g缓存分配锁.lock();
	
	分配释放记录[buf] = 分配释放记录.size();

	g缓存分配锁.unlock();
	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境& ctx, E_板载缓存类型 type, uint16 offset) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, offset, type, 0);
	assert(offset);
	g缓存分配锁.lock();
	
	分配释放记录[buf] = 分配释放记录.size();
	g缓存分配锁.unlock();
	return buf;
}

S_板载缓存* f_buffer_创建流(S_设备环境& ctx, E_板载缓存类型 type, uint16 offset) {
	uint32 Flags = E_板载缓存类型::e_着色端内存地址;

	S_板载缓存* buf = new S_VkArray缓存(ctx, type, f_getVk缓存类型(type | Flags), offset, 1);
	//buf->m_预分配空间 = false;
	buf->m_流 = true;

	std::lock_guard<std::mutex> guard(g缓存分配锁);
	分配释放记录[buf] = 分配释放记录.size();

	return buf;
}




void f_buf_release板载缓存(S_板载缓存* buf) {

	g缓存分配锁.lock();
	分配释放记录.erase(buf);
	g缓存分配锁.unlock();

#ifdef _DEBUG  
	
#else

#endif

	delete buf;
}

void f_buf_释放所有() {
	uint32 id = 0;
	for (auto& e : 分配释放记录) {
		std::cout<<e.second<<" :"<<id<<std::endl;
		delete e.first;
		++id;
	}
}



uint32 f_get缓存布局类型(E_板载缓存类型 memType) {
	uint32 mt = 0;
	switch (memType) {
		case e_UBO:		mt = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 
			break;
		case e_TBOs:	mt = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 
			break;
		case e_VBO:	
		case e_INDEX:	//mt = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; break;
		case e_SSBO:	mt = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 
			break;
		case e_SSBOd:	mt = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 
			break;
			//case e_INDEX:	mt = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; break;
		case e_光追底层加速结构:
		case e_光追顶层加速结构:
		case e_光追BVH:	mt = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; break;

		case E_板载缓存类型::e_纹理储存_Array: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;

		case E_板载缓存类型::e_IMAGE: mt = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; break;
		case E_板载缓存类型::e_IMAGE_Array: mt = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; break;
		

		case E_板载缓存类型::e_SAMPLER: mt = VK_DESCRIPTOR_TYPE_SAMPLER; break;

		case E_板载缓存类型::e_IMAGE_SAMPLER:
		case E_板载缓存类型::e_SAMPLER_Array: mt = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; break;

		case E_板载缓存类型::e_图像缓存: mt = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; break;
		
		default:
			break;
	}
	return mt;
}




void f_fill板载缓存(S_板载缓存* obj, const vector<vec3>& data, E_板载缓存类型 memType, S_设备环境& ctx) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(vec3);
	obj->f_fillData(data.data(), data.size() * sizeof(vec3));
}


void f_fill板载缓存(S_板载缓存* obj, const vector<uint32>& data, E_板载缓存类型 memType, S_设备环境& ctx) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(uint32);
	obj->f_fillData(data.data(), data.size() * sizeof(uint32));
}



void f_fill板载缓存(S_板载缓存* obj, const vector<Mat44f>& data) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(Mat44f);
	obj->f_fillData(data.data(), data.size() * sizeof(Mat44f));
}

void f_fill板载缓存(S_板载缓存* obj, const Mat44f* data, uint64 offset) {
	obj->f_map();
	((Mat44f*)obj->m_mappedPtr)[offset] = *data;
	obj->f_unmap();
}

void f_buf_set(S_板载缓存* obj, int8 val) {
	obj->f_map();
	memset(obj->m_mappedPtr, val, obj->m_Offset * obj->m_Size);
	obj->f_unmap();
}

void f_buf_fill(S_板载缓存* obj, const void* val, uint64 num) {
	obj->f_fillData(val, obj->m_Offset * num);
}





void f_buf_resize(S_板载缓存* obj, uint64 size) {
	//assert(size != 0);
	if (size) {
		if (obj->m_Size == size) return;

		uint64 bitsize = obj->m_Offset * size;

		obj->m_Size = size;
		obj->f_resize(bitsize);
	}
	else {
		obj->m_Size = 0;
	}
}

void f_buf_erase(S_板载缓存* obj, uint32 loc, uint32 num) {
	obj->f_map();
	uint64 offset = num * obj->m_Offset;
	uint64 len = obj->m_Size * obj->m_Offset - offset;
	for (uint64 i = loc * obj->m_Offset; i < len; ++i) {
		((uint8*)obj->m_mappedPtr)[i] = ((uint8*)obj->m_mappedPtr)[offset + i];
	}
	obj->m_Size -= num;
	obj->f_unmap();
}

bool f_resize板载缓存_Up(S_板载缓存* obj, uint64 size) {
	if (size > obj->m_Size) {
		uint64 bitsize = obj->m_Offset * size;
		obj->f_resize(bitsize);
	}
	obj->m_Size = size;
	return true;
}

//void f_change板载缓存(S_板载缓存* obj, E_板载缓存类型 memType) {
//	auto* temp = obj;
//	//f_create板载缓存(obj->m)
//}

//void f_popend板载缓存(S_板载缓存* obj, int64 id) {
//	if (id < 0) {
//		f_buf_resize(obj, obj->m_Size--);
//	}
//	else {
//		obj->f_map();
//		//((uint8*)obj->m_mappedPtr)[0] = data;
//		obj->f_unmap();
//	}
//}







void f_clear板载缓存(S_板载缓存* obj) {
	obj->f_resize(obj->m_Offset);
	obj->m_Size = 0;
}

void f_buf_insert(S_板载缓存* obj, int64 offset, const void* data, uint32 size) {
	assert(size);
	
	obj->m_Size += size;
	obj->f_resize(obj->m_Size * obj->m_Offset);
	
	
	uint64 startoffset = offset * obj->m_Offset;
	uint64 appendOffset = (offset + size) * obj->m_Offset;
	uint64 newDataSize = size * obj->m_Offset;
	uint64 后面一节数据的数量 = obj->m_Size - offset;

	void* temp = calloc(后面一节数据的数量, obj->m_Offset);
	后面一节数据的数量 *= obj->m_Offset;

	obj->f_map();
	memcpy(temp, &(((int8*)obj->m_mappedPtr)[startoffset]), 后面一节数据的数量);
	memcpy(&(((int8*)obj->m_mappedPtr)[appendOffset]), temp, 后面一节数据的数量);
	memcpy(&(((int8*)obj->m_mappedPtr)[startoffset]), data, newDataSize);
	obj->f_unmap();

	free(temp);
}

void f_bm_copy(S_GPU内存块& dst块, const S_GPU内存块& src块) {
	uint64 num = src块.m_Mem.m_数量;
	assert(dst块.m_Buf->m_Offset == src块.m_Buf->m_Offset);

	if (dst块.m_Buf->m_流) {
		auto data = std::make_unique<C_缓存块列队拷贝>(&dst块, src块);
		f_bm_添加更新缓存列队(std::move(data));
	}
	else {
		f_bm_resize(dst块, num);
		uint8* dst = &(((uint8*)dst块.m_Buf->m_mappedPtr)[dst块.m_Mem.m_偏移 * dst块.m_Buf->m_Offset]);
		uint8* src = &(((uint8*)src块.m_Buf->m_mappedPtr)[src块.m_Mem.m_偏移 * src块.m_Buf->m_Offset]);
		memcpy(dst, src, num * src块.m_Buf->m_Offset);
	}
}


/*void f_buf_resize(uint64 count, uint16 num, ...) {
	va_list 参数表;

	va_start(参数表, num);

	for (uint16 i = 0; i < num; ++i) {
		S_板载缓存* b = va_arg(参数表, S_板载缓存*);

		f_buf_resize(b, count);
	}

	va_end(参数表);
}*/


void f_bm_erase(S_GPU内存块& 块) {
	if (块.m_Mem.m_数量 > 0) {
		f_buf_gfree(块.m_Buf, 块.m_Mem);
		块.m_Mem = {};
	}
}

















